package com.stylefeng.guns.rest.test.Thread;

import cn.hutool.core.date.DateTime;
import com.google.common.collect.Lists;
import com.stylefeng.guns.core.support.DateTimeKit;
import org.junit.Test;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/***
 * @Author 张亚林
 * @Date 2019-03-04
 */
public class Thread1 {

    @Test
    public void test1() {
        Long start = System.currentTimeMillis();
        long sun = LongStream.range(1, 1000000).sum();
        long total = 0L;
        for (int i = 0; i < 1000000; i++) {
            total += i;
        }
        long end = System.currentTimeMillis();
        long cost = getDelay(start, end, TimeUnit.NANOSECONDS);
        System.out.printf("sum=%s,total=%s,cost=%sns", sun, total, cost);

    }

    @Test
    public void test11() {
        DateTime now = DateTime.now();
        DateTime bef = DateTime.of("2019-03-06 10:00:00", "yyyy-MM-dd HH:mm:ss");
        long diff = DateTimeKit.diff(bef, now, 3600 * 1000L);
        System.out.printf("相差时间:%s", diff);
    }

    /**
     * 让某一线程等待多个线程的状态，然后该线程被唤醒。
     */
    @Test
    public void countDownLatch() throws InterruptedException {
        int totalThread = 3;
        long start = System.currentTimeMillis();
        CountDownLatch countDown = new CountDownLatch(totalThread);
        for (int i = 0; i < totalThread; i++) {
            final String threadName = "Thread " + i;
            new Thread(() -> {
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, "started"));
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                countDown.countDown();
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, "ended"));
            }).start();
        }
        countDown.await();
        long stop = System.currentTimeMillis();
        System.out.println(String.format("Total time : %sms", (stop - start)));
    }

    /**
     * CyclicBarrier是让多个线程互相等待某一事件的发生，然后同时被唤醒。
     */
    @Test
    public void testCyclicBarrier() {
        int totalThread = 5;
        CyclicBarrier barrier = new CyclicBarrier(totalThread);
        for (int i = 0; i < totalThread; i++) {
            String threadName = "Thread " + i;
            new Thread(() -> {
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, " is waiting"));
                try {
                    barrier.await();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, "ended"));
            }).start();
        }
    }

    /**
     * Phaser比较适合这样一种场景，一种任务可以分为多个阶段，现希望多个线程去处理该批任务，对于每个阶段，多个线程可以并发进行，但是希望保证只有前面一个阶段的任务完成之后才能开始后面的任务。
     */
    @Test
    public void testPhaser() {
        int parties = 3;
        int phases = 4;
        final Phaser phaser = new Phaser(parties) {
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("====== Phase : " + phase + " ======");
                return registeredParties == 0;
            }
        };

        for (int i = 0; i < parties; i++) {
            int threadId = i;
            Thread thread = new Thread(() -> {
                for (int phase = 0; phase < phases; phase++) {
                    System.out.println(String.format("Thread %s, phase %s", threadId, phase));
                    phaser.arriveAndAwaitAdvance();
                }
            });
            thread.start();
        }
    }

    /**Stream 复用*/
    @Test
    public void testStreamReUse(){
        List<String> joins = Lists.newArrayList("1, 2, 3", "2, 3, 4", "3, 4, 5");
        Stream<Integer> stream01 = this.getStream(joins);
        Optional<Integer> reduce = stream01.reduce((a, b) ->{
                System.out.println("a=" + a + ",b=" + b);
               return a + b;});
        System.out.println(reduce);
        stream01 = this.getStream(joins);
        String reduce1 = stream01.map(x -> x.toString()).reduce("", String::concat);
        System.out.println(reduce1);



    }
    /**通过函数每次返回新的Stream对象*/
    public Stream<Integer> getStream(List<String> joins) {
        //  将字符转换为数字Stream
        return joins.stream().flatMap(str -> {
            String[] nums = str.split(",");
            //  将字符转换为数字
            return Arrays.asList(nums).stream().map(num -> {
                return Integer.parseInt(num.trim());
            });
        });
    }



    public long getDelay(long start, long end, TimeUnit unit) {

        return unit.convert(end - start, TimeUnit.NANOSECONDS);
    }


}
